export = {}

//https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#interfaces
/** An interface declaration is another way to name an object type*/
interface Point {
  x: number;
  y: number;
}
function printCoord(pt: Point) {
  console.log("The coordinate's x value is " + pt.x);
  console.log("The coordinate's y value is " + pt.y);
}
printCoord({ x: 100, y: 100 });


/**
接口不是类型 它们是不同维度的东西 它是用来定义类型的
使用接口能定义几乎任意结构的类型

--- js里万物皆对象, 对象的表现很复杂, 比如一个函数它即是函数又可以作为一个对象 可以有属性 甚至 这个函数上可以有方法属性
*/
/*
接口就是用代码描述一个对象必须有什么属性(包括方法), 但是有没有其他属性就不管了(即目标的属性可以多,但不能少)
+ 可以用来描述 对象、类、函数
+ 可以用来描述一个具有某些属性的函数什么的这种比较"混合"的情况下的类型

> TypeScript的核心原则之一是对值所具有的结构进行类型检查。 它有时被称做“鸭式辨型法”或“结构性子类型化”。 在TypeScript里，接口的作用就是为这些类型命名和为你的代码或第三方代码定义契约。
>
> One of TypeScript’s core principles is that type checking focuses on the shape that values have. This is sometimes called “duck typing” or “structural subtyping”.
>
> In TypeScript, interfaces fill the role of naming these types, and are a powerful way of defining contracts within your code as well as contracts with code outside of your project.

接口不是类型 它们是不同维度的东西 它是用来定义类型的
使用接口能定义几乎任意结构的类型

这里的接口 和 我们后端接口是一个功能
就是用来告诉你我这个东西肯定有什么玩意儿
/users/:id

id:xxx
name:xxx
nickname:xxx
age:xxx

只是typescript接口不仅限于定义属性,还可以定义方法
*/


/**
注意在定义接口的时候，你不要把它理解为是在定义一个对象，而要理解为{}括号包裹的是一个代码块，里面是一条条声明语句
，只不过声明的不是变量的值而是类型。
声明也不用等号赋值，而是冒号指定类型。
每条声明之前用换行分隔即可，或者也可以使用分号或者逗号，都是可以的。
*/

/**
 注意本节中所有接口都是用来描述一个对象的
 只是使用情景上又分为 赋值 和 传参
 */


/** 1. 接口表示一个对象必须要有什么属性
    还有一点值得提的是，类型检查器不会去检查属性的顺序，只要相应的属性存在并且类型也是对的就可以。*/
// 你可以把接口 翻译成 要求
interface Human {
  name: string;
  age: number;
}

// 源对象必须包含目标对象上的所有属性
let ahhh: Human = {name:'ahhh'}; // TS2741: Property 'age' is missing in type '{ name: string; }' but required in type 'Human'.


/** 2. 接口可以嵌套*/
interface Shape {
  head: string;
  body: string;
}
interface Human2 {
  name: string;
  age: number;
  shape: Shape;

  // 注意 和 `{(a:number, b:number):number}` 进行区分
  // ↓↓下面这个描述对象上的方法, 而 `{(a:number, b:number):number}` 是用接口描述的一个函数;
  say(word: string): void;
}

let ahhh2: Human2 = {name: 'ahhh2', age: 123, shape: {head: '○', body: '□'}, say(word:string){console.log(word)}};

ahhh2.say('I am ahhh2');


/** 3. 除了用interface关键字声明接口来描述对象,也可以直接使用下面这种写法↓*/
// let x:{a:string} = {a:'123'}


/** 4. 另外一种常用情景是用接口来限制函数的参数*/
function X(x:Human):void{}
X({name: 'ahhh2', age: 123});

//emmm 姑且称这种非interface关键字的写法为 对象字面量形式接口
function Y(x:{name:string; age: number;}):void{}
Y({name: 'ahhh2', age: 123});
